package com.base.controller;

import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
public class RedissonController {

    @Autowired
    private RedissonClient redissonClient;


    @GetMapping("/test")
    public String test() throws InterruptedException {

        RLock lock = redissonClient.getLock("test");
        log.info("进入方法,{}",Thread.currentThread().getId());

        try {
            // 默认过期30秒,在这期间如果有其他线程来竞争,会触发看门狗机制,每过10秒自动过期时间续期到30秒
            //lock.lock();
            //Thread.sleep(50000);
            // 在获取锁10秒钟以后,会自动释放锁
            //lock.lock(10, TimeUnit.SECONDS);
            // 场景:客户端A已经获取了一把锁,此时客户端B尝试去获取这把锁,默认情况下客户端B是无限制的等待,一直等客户端A释放锁
            // 此时可以指定一个时间10秒,客户端B在10秒内还没获取到锁就返回false,表示加锁失败,在指定的范围内没有获取到锁
            //boolean b = lock.tryLock(); // 获取不到锁直接返回false,不等待
            //boolean b = lock.tryLock(10, TimeUnit.SECONDS);
            boolean b = lock.tryLock(0, TimeUnit.SECONDS);
            if (b) {
                log.info("加锁成功，执行业务..." + Thread.currentThread().getId());
                Thread.sleep(50000);
                log.info("释放锁..." + Thread.currentThread().getId());
                // 注意: 使用unlock进行解锁的时候,解锁的线程一定要使用加锁的线程
                lock.unlock();
            }else {
                log.info("加锁失败，直接返回..." + Thread.currentThread().getId());
                return "获取锁失败";
            }

            // 异步加锁,用了其他线程去进行加锁,不会阻塞当前主线程的执行
            //lock.lockAsync();


            lock.unlock();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "ok";
    }


}
